﻿using DataMgr.mode;
using DataMgr.msg;
using DataMgr.msg.req;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using DataMgr.File;

namespace DataMgr
{
    class DownManager
    {
        public const int MAX_THREAD_COUNT = 4;
        private static Thread[] _downThread = new Thread[4];
        private static Hashtable m_downTask = new Hashtable();  //key=guid+chl, value=ReqDown
        //private static Hashtable m_testInfo = new Hashtable();  //key=ReqDown, value=ChannelTestInfo
        public static List<ChannelTestInfo> m_testInfo = new List<ChannelTestInfo>();
        //static object m_lockTestInfo = new object();
        public const string BTSDA_FILE_EXTENSION = ".bdf";
        public void BeginThread()
        {
            for (int i = 0; i < DownManager.MAX_THREAD_COUNT; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(RunDown));
                t.Start(i.ToString());
            }
        }

        static ChannelTestInfo GetTestInfo(string guidChl)
        {
            foreach (ChannelTestInfo item in m_testInfo)
            {
                if (item.DownKey == guidChl)
                    return item;
            }

            return null;
        }

        //接收客户端下载请求
        public static int RecDownMsg(string reqMsg)
        {
            ReqDown req = new ReqDown();
            req.Parse(reqMsg);

            string sKey = req.guidPath + req.chlId.ToString();
            lock (m_downTask)
            {
                if (!m_downTask.ContainsKey(sKey))
                {
                    m_downTask.Add(sKey, req);
                    ChannelTestInfo t = GetTestInfo(sKey);
                    if (t == null)
                    {
                        ChannelTestInfo chlInfo = new ChannelTestInfo();
                        chlInfo.State = DwonState.DOWN_REQUEST;
                        chlInfo.Request = req;
                        chlInfo.DownKey = sKey;
                        m_testInfo.Add(chlInfo);
                        
                    }

                }
            }
            MsgUtil.WriteLog("RecDownMsg " + req.guidPath);
            return 0;
        }


        //开始一个下载线程，threadIndex从0开始到MAX_THREAD_COUNT-1
        public static void RunDown(object oIndex)
        {
            int threadIndex = int.Parse(oIndex as string);
            MyDb myDb = new MyDb();
            myDb.Init();
            while (true)
            {
                // 获取键的集合 
                ICollection key = m_downTask.Keys;

                foreach (string k in key)
                {
                    //Console.WriteLine(k + ": " );
                    ReqDown req = m_downTask[k] as ReqDown;
                    int nDownIndex = req.chlId % MAX_THREAD_COUNT;//0到3
                    if (nDownIndex == threadIndex)
                    {
                        ChannelTestInfo t = GetTestInfo(k);
                        if (t == null)
                        {
                            continue;
                        }
                        DwonState nRet = DownBDF(ref t, myDb);
                        t.State = nRet;
                        t.LastUpdateTime = DateTime.Now;
                        if (DwonState.DWON_FINISH == nRet || DwonState.DOWN_ERROR == nRet)
                        {
                            m_downTask.Remove(k);
                            RemoveTask(req);
                            break;
                        }

                    }
                }

                Thread.Sleep(1000);
            }

            MsgUtil.WriteLog("线程退出 " + oIndex as string);
        }

        static void RemoveTask(ReqDown req)
        {

        }
        //开始一个下载任务,返回状态（0下载完成，1下载中，2未开始，3无法下载）
        public static DwonState DownBDF(ref ChannelTestInfo testInfo, MyDb myDb)
        {
            //if (!m_testInfo.ContainsKey(req))
            if (testInfo.State == DwonState.DOWN_REQUEST)
            {
                //ChannelTestInfo chlInfo = new ChannelTestInfo();
                if (myDb.QueryTestInfo(testInfo.Request.guidPath, (UInt16)testInfo.Request.chlId, ref testInfo))
                {
                    testInfo.State = DwonState.DOWN_DOING;
                }
                else
                {
                    MsgUtil.WriteLog("查询测试失败:" + testInfo.DownKey );
                    return DwonState.DOWN_ERROR;
                }
            }

            string sFold = MsgUtil.GetCfgString("Data", "dataFold") + "/";
            //ChannelTestInfo testInfo = m_testInfo[req] as ChannelTestInfo;
            string sFinishFile = sFold + GetFileName(testInfo, 0);
            if (System.IO.File.Exists(sFinishFile))
            {
                MsgUtil.WriteLog("文件已完成，不重复下载:" + sFinishFile);
                return DwonState.DWON_FINISH;
            }
            else
            {
                string sTmpFile = sFold + GetFileName(testInfo, 1);
                string sStepFile = MsgUtil.GetCfgString("Data", "stepFold") + "/" + testInfo.Request.guidStep + ".stp";
                if (!System.IO.File.Exists(sStepFile))
                {
                    MsgUtil.WriteLog(sTmpFile + "工步文件不存在:" + sStepFile);
                    return DwonState.DOWN_ERROR;
                }

                bool bFileExists = System.IO.File.Exists(sTmpFile);

                FileBdf bdf = new FileBdf();
                if (!bdf.CreateFile(sTmpFile))
                {
                    MsgUtil.WriteLog("文件打开/创建失败:" + sTmpFile);
                    return DwonState.DOWN_ERROR;
                }

                if (!bFileExists)
                {
                    bdf.WriteHead();    //1.写头
                    bdf.WriteChlInfo(testInfo.devChlInfo);  //2.写测试基本信息
                    bdf.WriteStepFile(sStepFile);  //3.写工步信息
                }

                Hashtable bmsTable = new Hashtable();
                List<SingleHisDfData> rList = myDb.QueryTestRecordData(testInfo.devChlInfo.devId,
                    testInfo.devChlInfo.testId, testInfo.devChlInfo.chlId, (UInt32)bdf.GetLastRecordSeq(), ref bmsTable); 
                UInt32 lastSeq = bdf.WriteBdfRecord(rList, bmsTable);  //4.写记录数据
                if (lastSeq > 0)
                    testInfo.LastSeq = lastSeq;

                List<SingleHisLogData> listLog = myDb.QueryTestLog(testInfo.devChlInfo.testId, testInfo.devChlInfo.chlId);
                if (listLog.Count > 0 && IsTestFinish(listLog[listLog.Count - 1]))
                {
                    bdf.WriteTestLog(listLog);    //5.写日志数据

                    //6.组织工步统计信息
                    List<STEP_STATIS> sList = myDb.QueryStepStatis(testInfo.devChlInfo.testId, testInfo.devChlInfo.chlId);
                    bdf.CalcStepStatis(ref sList);
                    bdf.WriteStepStatis(sList); //不写循环统计，DA自己统计

                    bdf.Finish();

                    FileInfo fi = new FileInfo(sTmpFile);
                    fi.MoveTo(sFinishFile);
                    return DwonState.DWON_FINISH;
                }
                else
                    return DwonState.DOWN_WAIT;
            }
        }

        public static bool IsTestFinish(SingleHisLogData log)
        {
            if (1 == log.nEvent || 5 == log.nEvent) //完成或者停止
                return true;
            else
                return false;
        }

        //参数type 0表示完成，1表示未完成
        public static string GetFileName(ChannelTestInfo t, int type)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            DateTime translateDate = startTime.AddSeconds(t.StartTime/1000);
            string strStrat = translateDate.ToString("yyyyMMddTHHmmss");
            string sFilename = strStrat + "_" + t.devChlInfo.devId.ToString() + "_" + t.devChlInfo.chlId.ToString();
            if (0 == type)
            {
                if (t.devChlInfo.barcode.Length > 0)
                {
                    return sFilename + "_" + t.devChlInfo.barcode + "_AT" + BTSDA_FILE_EXTENSION;
                }
                else
                    return sFilename + "_AT" + BTSDA_FILE_EXTENSION;
            }
            else
                return sFilename + "_AT_TMP";
        }

        

    }
}
